package com.ourway.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.liuweiheng.base.utils.BeanCopyUtil;
import com.liuweiheng.base.utils.HttpUtil;
import com.ourway.constant.FeiShuConstants;
import com.ourway.dao.DepartmentMapper;
import com.ourway.dao.FeiShuDepartmentSyncMapper;
import com.ourway.dtos.*;
import com.ourway.entity.*;
import com.ourway.entity.vo.FeiShuNormalResponseVo;
import com.ourway.entity.vo.PageResultDto;
import com.ourway.service.IDepartmentService;
import com.ourway.service.IFeiShuService;
import io.micrometer.core.instrument.util.StringUtils;
import org.json.JSONException;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;

/**
 * 部门接口服务实现类
 *
 * @author liuweiheng
 * @since 2021/12/11
 */
@Service
public class DepartmentServiceImpl implements IDepartmentService {

    private final DepartmentMapper departmentMapper;
    private final FeiShuDepartmentSyncMapper feiShuDepartmentSyncMapper;
    private final IFeiShuService feiShuService;
    private final FeiShuConstants feiShuConstants;

    public DepartmentServiceImpl(DepartmentMapper departmentMapper, FeiShuDepartmentSyncMapper feiShuDepartmentSyncMapper, IFeiShuService feiShuService, FeiShuConstants feiShuConstants) {
        this.departmentMapper = departmentMapper;
        this.feiShuDepartmentSyncMapper = feiShuDepartmentSyncMapper;
        this.feiShuService = feiShuService;
        this.feiShuConstants = feiShuConstants;
    }

    @Override
    public DepartmentDTO getTree() {
        // 先获取所有部门列表
        List<Department> listDepartment = departmentMapper.selectList(null);
        List<DepartmentDTO> listDepartmentDTO = BeanCopyUtil.copyListProperties(listDepartment, DepartmentDTO::new);
        final DepartmentDTO[] roots = new DepartmentDTO[1];
        listDepartmentDTO.stream()
                .filter(e -> StringUtils.isBlank(e.getParentId()))
                .findFirst()
                .ifPresent(s -> roots[0] = s);
        if (null == roots[0]) {
            return null;
        }

        DepartmentDTO root = roots[0];

        // 处理树结构
        Map<String, List<DepartmentDTO>> mapDeptIdChildren = new HashMap<>(listDepartmentDTO.size() / 2);
        listDepartmentDTO.forEach(e -> {
            String parentId = e.getParentId();
            e.setLabel(e.getName());
            if (StringUtils.isNotBlank(parentId)) {
                if (mapDeptIdChildren.containsKey(parentId)) {
                    mapDeptIdChildren.get(parentId).add(e);
                } else {
                    List<DepartmentDTO> list = new ArrayList<>(10);
                    list.add(e);
                    mapDeptIdChildren.put(parentId, list);
                }
            }
        });

        mapDeptIdChildren.forEach((key, value) -> {
            listDepartmentDTO.stream()
                    .filter(e -> e.getDepartmentId().equals(key))
                    .findFirst()
                    .ifPresent(s -> s.setChildren(value));
        });

        return root;
    }

    @Override
    public FeiShuDepartmentSync getSyncInfoByDeptId(String departmentId) {
        return new LambdaQueryChainWrapper<>(feiShuDepartmentSyncMapper)
                .eq(FeiShuDepartmentSync::getDepartmentId, departmentId)
                .one();
    }

    @Override
    public DepartmentDTO getByDeptId(String departmentId) {
        Department entity = new LambdaQueryChainWrapper<>(departmentMapper)
                .eq(Department::getDepartmentId, departmentId)
                .one();

        if (null == entity) {
            return null;
        }

        DepartmentDTO dto = new DepartmentDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    @Override
    public FeiShuDepartment getFeiShuDeptByOpenDeptId(String feishuOpenDepartmentId) {
        String tenantAccessToken = feiShuService.getTenantAccessToken();
        Map<String, String> header = new HashMap<>(1);
        header.put("Authorization", "Bearer " + tenantAccessToken);
        String url = feiShuConstants.getDepartmentInfoUrl(feishuOpenDepartmentId);
        String response = HttpUtil.getWithJsonSync(url, String.class, header);
        FeiShuNormalResponseVo responseVo = JSONUtil.toBean(response, FeiShuNormalResponseVo.class);
        boolean result = responseVo.getCode() == 0;

        if (result) {
            JSONObject data = JSONUtil.parseObj(responseVo.getData().toString());
            return JSONUtil.toBean(data.get("department").toString(), FeiShuDepartment.class);
        }
        return null;
    }

    @Override
    public PageResultDto<DepartmentDTO> getDeptList(int pageIndex, int pageSize) {
//        IPage<Department> deptPage = new Page<>(pageIndex, pageSize);
//        List<Department> deptList = departmentMapper.selectPage(deptPage, null).getRecords();
//        List<DepartmentDTO> departmentDtoList = BeanCopyUtil.copyListProperties(deptList, DepartmentDTO::new);

        List<DepartmentDTO> departmentDtoList = departmentMapper.findDeptListByPage(pageIndex, pageSize);
        int totalCount = departmentMapper.selectCount(null);
        return PageResultDto.<DepartmentDTO>builder()
                .dataList(departmentDtoList)
                .totalCount(totalCount)
                .build();
    }

    @Override
    public Boolean creteDept(DepartmentDTO departmentDTO) throws JSONException {
        // 检查上级部门
        CheckDeptResultDTO checkResult = checkDeptIsExist(departmentDTO.getParentId());
        if (checkResult.hasError) {
            throw new IllegalArgumentException(checkResult.getMessage());
        }

        Date now = new Date(System.currentTimeMillis());

        departmentDTO.setCreateTime(now).setUpdateTime(now).setDeleteFlag(0).setDepartmentId(StrUtil.uuid().replaceAll("-", ""));

        FeiShuDeptAddDTO feiShuDeptAddDTO = FeiShuDeptAddDTO.builder()
                .parentDepartmentId(checkResult.getFeiShuDepartmentSync().getFeishuOpenDepartmentId())
                .name(departmentDTO.getName()).build();

        // 飞书创建
        FeiShuDepartment feiShuDepartment = feiShuService.createDept(feiShuDeptAddDTO);

        // 数据库创建
        Department department = Department.dtoToEntity(departmentDTO);

        int insert = departmentMapper.insert(department);

        if (insert == 0) {
            return Boolean.FALSE;
        }

        // 写入同步数据
        FeiShuDepartmentSync feiShuDepartmentSync = FeiShuDepartmentSync.builder()
                .departmentId(departmentDTO.getDepartmentId())
                .feishuOpenDepartmentId(feiShuDepartment.getOpenDepartmentId())
                .feishuDepartmentId(feiShuDepartment.getDepartmentId())
                .createTime(now)
                .updateTime(now).build();
        feiShuDepartmentSyncMapper.insert(feiShuDepartmentSync);

        return Boolean.TRUE;
    }

    private CheckDeptResultDTO checkDeptIsExist(String deptId) {
        // 检查用户是否存在
        DepartmentDTO old = getByDeptId(deptId);
        if (null == old) {
            return CheckDeptResultDTO.error("部门尚未在本系统注册");
        }

        // 检查用户是否在飞书注册
        // 获取飞书映射ID
        FeiShuDepartmentSync feiShuDepartmentSync = getSyncInfoByDeptId(deptId);
        if (null == feiShuDepartmentSync) {
            return CheckDeptResultDTO.error("部门未同步到飞书");
        }

        // 查询飞书是否存在对象
        FeiShuDepartment feiShuDepartment = getFeiShuDeptByOpenDeptId(feiShuDepartmentSync.getFeishuOpenDepartmentId());
        if (null == feiShuDepartment) {
            return CheckDeptResultDTO.error("部门在飞书中未注册");
        }

        return CheckDeptResultDTO.success(null, old, feiShuDepartmentSync, feiShuDepartment);
    }

    @Override
    public Boolean update(DepartmentDTO departmentDTO) {

        departmentDTO.setUpdateTime(new Date(System.currentTimeMillis()));

        // 检查是否存在
        CheckDeptResultDTO checkDeptResultDTO = checkDeptIsExist(departmentDTO.getDepartmentId());
        if (checkDeptResultDTO.hasError) {
            throw new IllegalArgumentException(checkDeptResultDTO.getMessage());
        }

        // 检查父部门是否存在
        CheckDeptResultDTO checkParentResultDTo = checkDeptIsExist(departmentDTO.getParentId());
        if (checkParentResultDTo.hasError) {
            throw new IllegalArgumentException(checkDeptResultDTO.getMessage());
        }

        FeiShuDeptUpdateDTO feiShuDeptUpdateDTO = FeiShuDeptUpdateDTO.builder()
                .name(departmentDTO.getName())
                .parentDepartmentId(checkParentResultDTo.getFeiShuDepartmentSync().getFeishuOpenDepartmentId()).build();

        FeiShuDeptUpdateDTO old = FeiShuDeptUpdateDTO.builder().build();
        BeanUtils.copyProperties(checkDeptResultDTO.getFeiShuDepartment(), old);

        feiShuDeptUpdateDTO.setNoneUpdatePropertyNull(old);

        // 更新飞书
        String url = feiShuConstants.getUpdateDeptUrl(checkDeptResultDTO.getFeiShuDepartmentSync().getFeishuOpenDepartmentId());
        String accessToken = feiShuService.getTenantAccessToken();
        Map<String, String> header = new HashMap<>(1);
        header.put("Authorization", "Bearer " + accessToken);
        String response = HttpUtil.patchWithJsonSync(url, feiShuDeptUpdateDTO, String.class, header);

        FeiShuNormalResponseVo responseVo = JSONUtil.toBean(response, FeiShuNormalResponseVo.class);

        boolean result = responseVo.getCode() == 0;

        Assert.isTrue(result, "同步更新飞书失败");

        // 更新数据库
        Department department = new Department();
        BeanUtils.copyProperties(departmentDTO, department);
        int updateCount = departmentMapper.updateById(department);
        if (updateCount == 0) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    @Override
    public Boolean delete(DepartmentDTO departmentDTO) {

        CheckDeptResultDTO checkDeptResultDTO = checkDeptIsExist(departmentDTO.getDepartmentId());

        String feishuOpenDeptId = checkDeptResultDTO.getFeiShuDepartmentSync().getFeishuOpenDepartmentId();

        String url = feiShuConstants.getUpdateDeptUrl(feishuOpenDeptId);
        String accessToken = feiShuService.getTenantAccessToken();
        Map<String, String> header = new HashMap<>(1);
        header.put("Authorization", "Bearer " + accessToken);
        String response = HttpUtil.delete(url, FeiShuDeptUpdateDTO.builder().build(), String.class, header);

        FeiShuNormalResponseVo responseVo = JSONUtil.toBean(response, FeiShuNormalResponseVo.class);

        boolean result = responseVo.getCode() == 0;

        Assert.isTrue(result, "同步删除部门飞书失败");

        LambdaQueryWrapper<Department> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Department::getDepartmentId, departmentDTO.getDepartmentId());
        int delete = departmentMapper.delete(wrapper);

        if (delete == 0) {
            return Boolean.FALSE;
        }

        LambdaQueryWrapper<FeiShuDepartmentSync> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(FeiShuDepartmentSync::getDepartmentId, departmentDTO.getDepartmentId());
        int delete1 = feiShuDepartmentSyncMapper.delete(wrapper2);

        if (delete1 == 0) {
            return Boolean.FALSE;
        }

        return Boolean.TRUE;
    }
}
